package com.thinkTank.oa.configuration;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.stereotype.Component;

import com.github.pagehelper.StringUtil;
import com.thinkTank.oa.common.UserInfo;
import com.thinkTank.oa.dao.OperationlogMapper;
import com.thinkTank.oa.entity.ButtDetails;
import com.thinkTank.oa.entity.Operationlog;
import com.thinkTank.oa.util.StrUtil;

/**
 * 定义切面
 * 
 * @author dq
 * 插入日志操作
 *
 */
@Aspect
@Component
public class LogAspect {
	
	@Autowired
	private OperationlogMapper operationlogMapper;
	
	@Pointcut("@annotation(com.thinkTank.oa.configuration.Log)")
    public void pointcut() { }
	
	
	 @Around("pointcut()")
	    public Object around(ProceedingJoinPoint point) {
	        Object result = null;
	        long beginTime = System.currentTimeMillis();
	        try {
	            // 执行方法
	            result = point.proceed();
	        } catch (Throwable e) {
	            e.printStackTrace();
	        }
	        // 执行时长(毫秒)
	        long time = System.currentTimeMillis() - beginTime;
	        // 保存日志
	        saveLog(point, time);
	        return result;
	    }
		private void saveLog(ProceedingJoinPoint joinPoint, long time) {
	        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
	        Method method = signature.getMethod();
	        Parameter[] parameters = method.getParameters();
	        int refIndex = IntStream.range(0, parameters.length).filter(i -> parameters[i].isAnnotationPresent(RefPid.class)).findAny().orElse(-1);
	        Operationlog sysLog = new Operationlog();
	        Log logAnnotation = method.getAnnotation(Log.class);
	        if (logAnnotation != null) {
	            // 注解上的描述
	            sysLog.setOperation(logAnnotation.value());
	        }
	        // 请求的方法名
			String className = joinPoint.getTarget().getClass().getName();
	        String methodName = signature.getName();
	        sysLog.setMethod(className + "." + methodName + "()");
	        // 请求的方法参数值
	        Object[] args = joinPoint.getArgs();
	        // 请求的方法参数名称
	        LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();
	        String[] paramNames = u.getParameterNames(method);
	        if (args != null && paramNames != null) {
	            String params = "";
	            for (int i = 0; i < args.length; i++) {
	                Object obj = args[i];
					params += "  " + paramNames[i] + ": " + obj;
	                if (i == refIndex) {
	                	String refPid = obj.toString();
	                	if (obj instanceof ButtDetails) {
	                		//如果是对接详情则保存2个对接条目
	                		ButtDetails bd = (ButtDetails) obj;
	                		refPid = Stream.of(bd.getProjectNumber(), bd.getDemandNumber(), bd.getCustomerNumber(), bd.getExpertNumber(), bd.getConferenceNumber())
	                			.map(number -> StringUtil.isEmpty(number) ? "x" : number).collect(Collectors.joining(","));
	                	} else if (!(obj instanceof String)) {
	                		try {
								Field pidField = obj.getClass().getDeclaredField("pid");
								pidField.setAccessible(true);
								refPid = pidField.get(obj).toString();
							} catch (Exception e) {
								e.printStackTrace();
							} 
	                	}
	                	sysLog.setRefPid(refPid);
	                }
	            }
	            //可能太长了
	            params = params.length() > 1024 ? params.substring(0, 1024) : params;
	            sysLog.setParams(params);
	        }
	        // 获取request
	        HttpServletRequest  request = StrUtil.getCurrentRequest();
	   
	        UserInfo userinfo=  (UserInfo) request.getSession().getAttribute("userInfo");
	        // 设置IP地址
	        sysLog.setIp(getIpAddr(request));
	        // 模拟一个用户名
	        sysLog.setUsername(userinfo.getFullName());
	        sysLog.setUserId(userinfo.getUserId());
	        sysLog.setTime((int) time);
	        sysLog.setCreateTime(StrUtil.getCurrentDateTime_two());
	        
	        // 保存系统日志
	        operationlogMapper.add(sysLog);
	    }
		private  String getIpAddr(HttpServletRequest request) {
			String ip = request.getHeader("x-forwarded-for");
			if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
				ip = request.getHeader("Proxy-Client-IP");
			}
			if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
				ip = request.getHeader("WL-Proxy-Client-IP");
			}
			if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
				ip = request.getRemoteAddr();
			}
			return ip;
		}

}
